package org.dromara.demo.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.annotation.SaMode;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.demo.domain.bo.JsExecuteBo;
import org.dromara.demo.domain.bo.JsSuiteBo;
import org.dromara.demo.domain.vo.JsExecuteVo;
import org.dromara.demo.domain.vo.JsSuiteVo;
import org.dromara.demo.service.IJsExecuteService;
import org.dromara.demo.service.IJsSuiteBasicVarService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.demo.service.IJsSuiteService;
import org.dromara.common.mybatis.core.page.TableDataInfo;

/**
 * 用例执行
 *
 * @author zhu
 * @date 2024-12-31
 */
@Validated
@RequiredArgsConstructor
@RestController
@Slf4j
@RequestMapping("/demo/suite")
public class JsSuiteController extends BaseController {

    private final IJsSuiteService jsSuiteService;

    private final IJsExecuteService jsExecuteService;

    /**
     * 查询用例执行列表
     */
    @GetMapping("/list")
    public TableDataInfo<JsSuiteVo> list(JsSuiteBo bo, PageQuery pageQuery) {
        return jsSuiteService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出用例执行列表
     */
    @Log(title = "用例执行", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(JsSuiteBo bo, HttpServletResponse response) {
        List<JsSuiteVo> list = jsSuiteService.queryList(bo);
        ExcelUtil.exportExcel(list, "用例执行", JsSuiteVo.class, response);
    }

    /**
     * 获取用例执行详细信息
     *
     * @param id 主键
     */
    @GetMapping("/{id}")
    public R<JsSuiteVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(jsSuiteService.queryById(id));
    }

    /**
     * 新增用例执行
     */
    @Log(title = "用例执行", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody JsSuiteBo bo) {
        return toAjax(jsSuiteService.insertByBo(bo));
    }

    /**
     * 修改用例执行
     */
    @Log(title = "用例执行", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody JsSuiteBo bo) {
        return toAjax(jsSuiteService.updateByBo(bo));
    }

    /**
     * 删除用例执行
     *
     * @param ids 主键串
     */
    @Log(title = "用例执行", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(jsSuiteService.deleteWithValidByIds(List.of(ids), true));
    }

    /**
     * 导出测试报告
     */
    @Log(title = "用例执行", businessType = BusinessType.EXPORT)
    @PostMapping("/exportReport")
    @SaIgnore
    public void exportReport(JsSuiteBo bo, HttpServletResponse response) {
        jsSuiteService.exportReport(bo, response);
    }

    /**
     * 查询测试用例列表
     */
    @PostMapping("/start")
    public R<Void> execute(@RequestBody JsSuiteBo bo) {
        JsExecuteBo jsExecuteBo = new JsExecuteBo();
        jsExecuteBo.setSuiteId(bo.getId());
        jsExecuteBo.setSuiteName(bo.getName());
        jsExecuteService.insertByBo(jsExecuteBo);
        // 调用python exe 文件
        String exePath = bo.getExamplePath();
        String[] split = exePath.split(",");
        // Python解释器的路径
        String pythonInterpreter = "/Users/joron314/PycharmProjects/JohnsonControl-Hitachi/venv/bin/python";

        for (String s : split) {
            // 使用Runtime执行exe文件
            ProcessBuilder pb = new ProcessBuilder(pythonInterpreter,s, jsExecuteBo.getId().toString());
            try {
                // 启动进程
                Process process = pb.start();
                // 存储进程以便后续终止
                RedisUtils.setCacheObject("runningProcesses:"+jsExecuteBo.getId(), process.pid(), Duration.ofHours(1));
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
                String line;
                while ((line = reader.readLine()) != null) {
                    log.info(line);
                }
                // 等待命令执行完成
                int exitCode = process.waitFor();
                if (exitCode != 0) {
                    jsExecuteService.deleteWithValidByIds(List.of(jsExecuteBo.getId()), true);
                    RedisUtils.deleteObject("runningProcesses:"+jsExecuteBo.getId()); // 移除已终止的进程
                    throw new ServiceException("sys.python.script.execution.failed");
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
        return R.ok("执行成功");
    }

    @GetMapping("/stop")
    public R<Void> stopExecution() {
        JsExecuteVo jsExecuteVo = jsExecuteService.queryLast();
        if (jsExecuteVo == null) {
            return R.fail("未找到对应的执行进程，或者程序执行完毕");
        }
        // 假设你有一个映射来存储正在运行的进程
        Integer pid = RedisUtils.getCacheObject("runningProcesses:"+ jsExecuteVo.getId());
        if (pid != null) {// 终止进程
            // 根据pid 终止进程
            try {
                ProcessHandle handle = ProcessHandle.of(pid).orElse(null);
                if (handle != null) {
                    handle.destroy();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            RedisUtils.deleteObject("runningProcesses:"+ jsExecuteVo.getId());
            return R.ok("执行已停止");
        } else {
            return R.fail("未找到对应的执行进程，或者程序执行完毕");
        }
    }

//    public static void main(String[] args) {
//        String pythonInterpreter = "python";
//
//            // 使用Runtime执行exe文件
//            ProcessBuilder pb = new ProcessBuilder(pythonInterpreter,"D:\\appuim\\test.py","aaa");
//            try {
//                // 启动进程
//                Process process = pb.start();
//                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
//                String line;
//                while ((line = reader.readLine()) != null) {
//                    log.info(line);
//                }
//                // 等待命令执行完成
//                int exitCode = process.waitFor();
//                if (exitCode != 0) {
//                    throw new ServiceException("Python脚本执行失败");
//                }
//            } catch (IOException | InterruptedException e) {
//                e.printStackTrace();
//            }
//    }
}
